BEP-20: AER interface

Abstract: Address Event Representation is a format used to communicate to and
from neuromorphic chips with timed events (spikes). The goal is to be able
to listen to AER events and send AER events.

The idea is to interface with the JAVA program jAER, which can communicate
with a chip: http://sourceforge.net/projects/jaer/
There are two different issues:
* communicating with the program (jAERviewer) to send/receive AER events
* running Brian in realtime and feed/send AER events

See dev/ideas/AER for scripts.

Listening to jAERviewer
=======================
First steps with jAERviewer:
* Run jAERviewer
* Click on File > Remote > enable unicast...
* Check that the value of timestampMultiplier has a dot and not a comma
  (this is a bug due to French localisation)
* You can change the UDP port as you like (make sure your firewall allows
  communications through it).
* You may also change the buffer size (size of packets).
* We probably want to check useLocalTimestampsEnabled, it seems to output
  timestamps in microseconds (but there are some weird problems, sign problems,
  maybe it's little endian in this case).
* Drag and drop or open a file with AER events

Now jAERviewer plays the events and send them as packets through the UDP port.
Packets are in the following format:
Format:
int32 sequenceNumber
int32 address0
int32 timestamp0
int32 address1
int32 timestamp2
etc

with java's big-endian format. Note that this can be changed when you set
the UDP connection (for example, sequenceNumber is optional; you can also
have little-endian instead, or change the type of timestamps).
* sequenceNumber is the number of the packet. Normally, it should just increase
  by 1 after every packet. So the use of this is probably to check that you
  haven't missed a packet. Then follows a list of events in the form
  (address, timestamp)
* address is a chip-specific way to identify the event (e.g. pixel index).
* timestamp is the time of the event, in unknown units (but ints). Looks like
  microseconds or even smaller units.

For the 128x128 retina chip, the 32 bit address is formatted as follows:
1 bit	polarity (ON/OFF event)
7 bits	x
7 bits	y
There's a function extract_retina_event in AERlisten.py to extract the
information, but we should try to vectorise this.

Using the socket module, it's very simple to listen to these events.
There's still a little bit of work to make it more efficient.

TODO:
* check the units of timestamp (and that local option)
* perhaps write other functions for different chips, we probably just need to
  adapt Matlab functions:
  http://jaer.svn.sourceforge.net/viewvc/jaer/trunk/host/matlab/
  See this for the silicon cochlea:
  http://jaer.svn.sourceforge.net/viewvc/jaer/trunk/host/matlab/cochlea/extractCochleaEventsFromAddr.m?revision=429&content-type=text%2Fplain

Sending events to jAERviewer
============================
I haven't looked at this yet, but it seems fairly straightforward.
In principle:
* Enable it on the viewer: File>Remote>Open unicast...
* Send UDP packets in the same format.

Controlling chips through jAERviewer
====================================
It seems that we can communicate through UDP to send chip commands to
jAERviewer. More precisely, to set biases, which are the parameters on the
chip:
http://sourceforge.net/apps/trac/jaer/wiki/Interfacing%20to%20jAER

Reading/writing AER .dat files
==============================
Read:
http://jaer.svn.sourceforge.net/viewvc/jaer/trunk/host/matlab/loadaerdat.m?revision=2001&content-type=text%2Fplain
Save:
http://jaer.svn.sourceforge.net/viewvc/jaer/trunk/host/matlab/saveaerdat.m?revision=2001&content-type=text%2Fplain

If we don't want real-time, this should the easiest way: just load a previously
recorded AER file and use Brian to play it as an input (SpikeGeneratorGroup).

An example is given in loadAER.py (seems to work).

Feeding Brian with AER events
=============================
One simple possibility is to do it offline: record an AER file with jAERviewer,
then load them in Brian into a SpikeGeneratorGroup. This seems relatively
straightforward, except perhaps SpikeGeneratorGroup might be a little slow
(see below).

Real-time Brian
---------------
If we want to do it online, then Brian has to run in real time. So first of all,
the timestep must be large enough so that it's possible.
Here's the idea that is implemented in brianRT.py and in
experimental/neuromorphic/realtime.py.
To ensure reliable processing, Brian must have a processing latency. That is,
all AER events are postponed by a fixed latency. During the simulation, we
measure the real time (time()) and try to synchronize the Brian clock more or
less with it by inserting pauses (sleep()). More precisely, if
we don't want to miss events, then Brian must always be ahead of real time by
no more than the latency (otherwise events could be scheduled at a time that
has already passed).
Here's a simple algorithm to do this:
* Have a network_operation running every T.
* The operation checks if briantime>realtime, in which case it sleeps to catch
  up with real time.
If Brian runs faster than real time, this ensures that Brian is always less than
T ahead of real time. In practice, with overheads and temporary slow downs of
the simulation, it will be a little bit more. Thus events should be postponed
by a bit more than T.

Note that only one clock may be synchronized with real time.
This algorithm could be implemented has an object in Brian. For example,
as an option in run(). Or as a special Clock, or a dedicated function or object
(RealtimeController or something like that).
I think that since only one clock can be synchronized to real time, it would
make sense to have it as an option to run, e.g.:
run(realtime=myclock) # e.g. defaultclock
This would just add an object to the network.
There is an important parameter to set, which is T. But since the synchronizing
operation is a small overhead, it could simply be set by default to a fixed
value, perhaps a few ms. A global preference could be used to set it.
Then the only possibly remaining parameter is the
starting point of the clock. In principle, when the simulation runs, the
real time clock should be offset so that it matches the simulation clock.

Should there be a warning or an error if Brian cannot run as fast as real
time?

Another thing is we might to lock Brian to the speed of AER events rather
than to real time, in case it's not the same.

Feeding events
--------------
Look at monitor_AER_events for an example.

I think we first need to use a non-blocking socket to listen to events
(otherwise we need a thread): mysocket.setblocking(0).
Listening can be implemented as a network_operation.
The simplest way to feed events is to define a SpikeGeneratorGroup and add
events to the spike list, e.g.:
S.spiketimes+=event_list
(assuming the events are sorted by time, and they should be)

We also need to synchronize the starting time of events with the real time
clock. In addition, there's the problem of repetition in the viewer, where
time goes back to the beginning. Thus we should check whether time decreases,
in which case we should re-synchronize.

Efficiency
----------
Currently, SpikeGeneratorGroup loops over events, and this is probably not
very efficient if we have many events. There is also the issue of units
(we currently need to multiply all timestamps by second).
Maybe a digitized version would be better. It would basically work as the
LS structure (SpikeContainer object). In fact, I think since it inherits from
NeuronGroup, we just need to redefine init() and push_spikes(), and the rest
comes from NeuronGroup.
(Actually it could be the default behavior when it is initialized with spike times
rather than a generator).
Another (perhaps simpler) option is to allow the next spike iterator in
SpikeGeneratorGroup to return vectors of neurons (for the same timing)
(actually this might already work).

In fact, this numpy command should be used:
u, indices = unique(timestamp, return_index=True)
Then the idea would be to use a SpikeContainer which would not necessarily store
all timesteps but only non-empty ones (there would also be circular vector
storing the timestamps).

Current state
=============
* Loading AER files seems fine now.
* SpikeGeneratorGroup.gather() is too slow, and running a gathered group is
  too slow. The problem is that the design of SpikeGeneratorThreshold.__call__()
  is rather bad. It uses a where() function on a N-sized array with ones at
  positions of spikes. Very inefficient.
* SpikeQueue now replaces SpikeGeneratorGroup. Running is faster, but construction
  is slower, and overall it is not faster (why?).
* monitor_AER_events listens to spikes through UDP.

TODO
====
* Write SpikeQueue.push_spiketimes
* Make SpikeQueue faster for construction
* Make a cleaner version of SpikeQueue. This could rely on a new
  SpikeContainer with future events (in addition to past events, or independently)
  (FutureSpikeContainer).
* We have some problems with timestamps through UDP which are sometimes <0. Why?
* monitor_AER_events: feed the SpikeQueue with it. Can we do it in real time?